package com.dissertation.service.impl;

import com.dissertation.pojo.*;
import com.dissertation.service.IStatisticsService;
import com.dissertation.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class IndexStatistics implements IStatisticsService {

    @Autowired
    MongoTemplate template;

    @Override
    public List<IndexStatisticWrapBean> groupByCategoryTree( String categoryTreeName ) {
        Criteria match = getCriteriaMatch( categoryTreeName );
        Aggregation aggregation = Aggregation.newAggregation( match(match),
                    group( "categoryLeafName" ).count().as( "count" )
                    .avg( "completeRate" ).as( "completeRate" )
                    .first( "categoryTreeName" ).as( "categoryTreeName" )
                    .first( "categoryLeafName" ).as( "categoryLeafName" )
                );

        AggregationResults<IndexStatisticBean> results = template.aggregate( aggregation,
                "assets", IndexStatisticBean.class );
         return results.getMappedResults().stream()
                .collect( Collectors.groupingBy( IndexStatisticBean::getCategoryTreeName ) )
                 .entrySet().stream().map( stringListEntry -> new IndexStatisticWrapBean( stringListEntry.getKey(),
                 stringListEntry.getValue()) ).collect( Collectors.toList() );
    }

    private Criteria getCriteriaMatch( String categoryTreeName ) {
        Criteria match = Criteria.where( "deleted" ).is( false )
                .and( "categoryLeafName" ).exists( true );
        if ( categoryTreeName != null ) {
            match.and( "categoryTreeName" ).is( categoryTreeName );
        }
        return match;
    }

    @Override
    public List<YearStatisticWrapBean> getCountMonth( String categoryTreeName ) {
        Criteria match = getCriteriaMatch( categoryTreeName );
        match.and( "date" ).gt( DateUtils.getRecentTreeYear() );
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match( match ),
                project( "categoryLeafName", "categoryTreeName" )
                        .andExpression( "substr('$date',0,4)" ).as( "year" ),
                group( "categoryLeafName", "year" ).count().as( "count" )
                        .first( "categoryLeafName" ).as( "categoryLeafName" )
                        .first( "categoryTreeName" ).as( "categoryTreeName" )
                        .first( "year" ).as( "year" )
        );

        List<YearStatisticBean> result = template.aggregate( aggregation,
                "assets", YearStatisticBean.class )
                .getMappedResults();


        Map<String, List<YearStatisticBean>> map = result.stream().collect( Collectors.groupingBy( YearStatisticBean::getYear ) );
        return map.entrySet().stream()
                .map( stringListEntry ->
                        new YearStatisticWrapBean( stringListEntry.getValue().get( 0 ).getCategoryTreeName(),
                                stringListEntry.getKey(), stringListEntry.getValue() ) ).collect( Collectors.toList() );
    }


}
